<?php

namespace ChatGPT;

class sdk
{
    protected static $model = 'moonshot-v1-8k';
    protected static $apiKey = '';
    protected static $temperature = 0.3;
    protected static $max_tokens = 1000;
    protected static $channel = 'gpt';
    protected static $diyHost = '';
    protected static $diyKey = '';

    /**
     * sdk constructor.
     * @param string $apiKey
     * @param string $model
     * @param string $temperature
     * @param string $max_tokens
     */
    public function __construct($apiKey = '', $model = '', $temperature = '', $max_tokens = '')
    {
        if ($model) {
            self::$model = $model;
        }
        if ($temperature) {
            self::$temperature = $temperature;
        }
        if ($max_tokens) {
            self::$max_tokens = $max_tokens;
        }
        self::$apiKey = $apiKey;
    }

    public function setChannel($channel = '')
    {
        self::$channel = $channel;
    }

    public function setDiyHost($host = '')
    {
        self::$diyHost = $host;
    }

    public function setDiyKey($key = '')
    {
        self::$diyKey = $key;
    }
    public function sendText35($question = [], $stream = true)
    {
       
        $url = 'https://api.moonshot.cn/v1/chat/completions';
        $post = [
            'messages' => $question,
            'max_tokens' => self::$max_tokens,
            'temperature' => self::$temperature,
            'model' => self::$model,
            'frequency_penalty' => 0,
            'presence_penalty' => 0.6,
            'stream' => $stream
        ];
       $this->httpRequest($url, json_encode($post));

    }

    public function getModelList()
    {
        $url = 'https://api.openai.com/v1/models';
        return $this->httpRequest($url);
    }

    /**
     * @return array|mixed
     * 查询账户余额
     */
    public function getBalance()
    {
        $now = time();
        $startDate = date('Y-m-01', $now);
        $endDate = date('Y-m-d', $now);

        if (self::$channel == 'diy') {
            return $this->requestDiyApi('getBalance');
        } elseif (self::$channel == 'agent') {
            $usageUrl = self::$diyHost . '/v1/dashboard/billing/usage?start_date=' . $startDate . '&end_date=' . $endDate;
            $subUrl = self::$diyHost . '/v1/dashboard/billing/subscription';
        } else {
            // $url = 'https://api.openai.com/dashboard/billing/credit_grants';
            $usageUrl = 'https://api.openai.com/v1/dashboard/billing/usage?start_date=' . $startDate . '&end_date=' . $endDate;
            $subUrl = 'https://api.openai.com/v1/dashboard/billing/subscription';
        }

        $result= $this->httpRequest($usageUrl);
        $total_used = round($result['total_usage'] / 100, 3);

        $result = $this->httpRequest($subUrl);
        $total_granted = round($result['hard_limit_usd'], 3);
        $total_available = round(($total_granted * 1000 - $total_used * 1000) / 1000, 3);

        return [
            'total_granted' => $total_granted,
            'total_used' => $total_used,
            'total_available' => $total_available
        ];
    }

    /**
     * @param $api
     * @param $message
     * @return array|mixed
     * 请求自定义接口
     */
    private function requestDiyApi($api, $message = null)
    {
        
        $post = [
            'diyKey' => self::$diyKey,
            'apiKey' => self::$apiKey,
            'api' => $api,
            'model' => self::$model,
            'temperature' => self::$temperature,
            'max_tokens' => self::$max_tokens
        ];
        if (!empty($message)) {
            $post['message'] = $message;
        }
        $this->httpRequest(self::$diyHost, base64_encode(json_encode($post)));
    }

    /**
     * http请求
     */
    protected function httpRequest($url, $post = '')
    {

        $this->disableAllBuffer();
        $ch = curl_init();
        header("Content-Type: text/event-stream;charset=UTF-8");
        header("Cache-Control: no-cache");
        header("Connection: keep-alive");
        header("X-Accel-Buffering: no");
        header("Pragma: no-cache");
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); // 流模式：不缓存响应
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 开发环境禁用 SSL 校验（生产环境开启）
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Authorization: Bearer ' . self::$apiKey,
            'Accept: text/event-stream' // 告诉第三方接口：需要流输出
        ]);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        curl_setopt($ch, CURLOPT_TIMEOUT, 120); // 120 秒超时（与大模型 API 匹配）
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); // 连接超时 30 秒
        curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) {
            echo $data;
            flush(); // 刷新服务器缓冲（无需 ob_flush()，已禁用缓冲）
            return strlen($data); // 关键 3：返回数据块长度（cURL 必须要求）
        });
        curl_exec($ch);
        if (curl_errno($ch)) {
            return [
                'errno' => 1,
                'message' => 'curl 错误信息: ' . curl_error($ch)
            ];
        }
        curl_close($ch);
    }
    // 禁用所有缓冲（TP5 环境关键）
    private function disableAllBuffer()
    {
        // 关闭 PHP 全局缓冲
        ini_set('output_buffering', 'Off');
        // 关闭 zlib 压缩（避免自动缓存）
        ini_set('zlib.output_compression', 'Off');
        // 关闭所有已开启的缓冲层
        while (ob_get_level() > 0) {
            ob_end_flush();
        }
        // 开启隐式刷新（echo 后自动推送）
        ob_implicit_flush(true);
    }
    
}
